﻿using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp.Demos.SimplePipeline
{
    public static partial class Extensions
    {
        public static T Get<T>(this IFeatureCollectionByCustom features)
            => features.TryGetValue(typeof(T), out var value) ? (T)value : default(T);

        public static IFeatureCollectionByCustom Set<T>(this IFeatureCollectionByCustom features, T feature)
        {
            features[typeof(T)] = feature;
            return features;
        }

        public static WebHostBuilderByCustom UseHttpListenerServerByCustom(this WebHostBuilderByCustom webHostBuilderByCustom, params string[] urls)
        {
            webHostBuilderByCustom.HostBuilder.ConfigureServices(svcs =>
            {
                // 使用框架的容器
                // 注册一个自定义的 IServer
                svcs.AddSingleton<IServerByCustom>(new HttpListenerServerByCustom(urls));
            });

            return webHostBuilderByCustom;
        }

        public static WebHostBuilderByCustom ConfigureByCustom(this WebHostBuilderByCustom builder, Action<IApplicationBuilderByCustom> configure)
        {
            configure?.Invoke(builder.ApplicationBuilder);
            return builder;
        }


        public static IHostBuilder ConfigureWebHostByCustom(this IHostBuilder hostBuilder,
            Action<WebHostBuilderByCustom> configure)
        {
            // 将 Host 和自定义 App 关联起来
            var webHostBuilderByCustom = new WebHostBuilderByCustom(hostBuilder, new ApplicationBuilderByCustom());

            // 执行 Lambda 配置钩子 - 开始
            configure?.Invoke(webHostBuilderByCustom);
            // 执行 Lambda 配置钩子 - 结束

            // 这也是一种编程方法，将方法内部创建的一个配置对象，通过 Lambda 配置钩子的方式，在调用方进行设置


            // -------------------------------------------------

            // 外部配置完成后，开启启动服务

            // 上面的 Invoke 方法中注入了一个 IServerByCustom
            // 而且在 WebHostBuilderByCustom.ApplicationBuilder 中添加了一些 Middlewares

            // 继续对框架 IHostBuilder 中的 Services 进行配置
            hostBuilder.ConfigureServices(svcs =>
            {
                // 添加一个 IHostedService <WebHostedServiceByCustom> 对象
                // 这个对象就是服务的入口
                // 这个对象的 StartAsync 和 StopAsync 负责服务的开启和停止  
                svcs.AddSingleton<IHostedService>(provider =>
                {
                    // 构建 Middleware 调用链
                    RequestDelegateByCustom handler = webHostBuilderByCustom.ApplicationBuilder.Build();

                    // 从容器中获取前面外部配置中注入的 IServerByCustom <HttpListenerServerByCustom>
                    IServerByCustom server = provider.GetRequiredService<IServerByCustom>();

                    // 最终构建这个自定义 IHostedService
                    // 当应用启动时，框架识别到容器中有这个类型，就会调用其 StartAsync 方法                    
                    return new WebHostedServiceByCustom(server, handler);
                });

            });

            return hostBuilder;
        }

        public static Task WriteAsyncByCustom(this HttpResponseByCustom response, string contents)
        {
            var buffer = Encoding.UTF8.GetBytes(contents);
            return response.Body.WriteAsync(buffer, 0, buffer.Length);
        }
    }
}
